/*
 * traininfo_transfer.c
 *
 *  Created on: 2013-2-14
 *      Author: panqiuhui
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <pthread.h>

#include "../head/common_struct/traininfo.h"
#include "../head/common_struct/stationlist.h"
#include "../head/common_struct/start_end_stationlist.h"
#include "../head/common_struct/ticketlist.h"
#include "../head/communicate_with_client/traininfo_transfer.h"
#include "../head/dao/traininfo_dao.h"
#include "../head/dao/ticketinfo_dao.h"

//负责接受与火车相关的请求的线程的启动函数
void *traininfo_thread_function(void *arg) {
	//启动线程
	int port = *(int *) arg;

	int server_socketfd, client_socketfd;
	int server_len, client_len;
	struct sockaddr_in server_address;
	struct sockaddr_in client_address;
	int result;
	int maxfd;
	fd_set readfds, tempfds;

	server_socketfd = socket(AF_INET, SOCK_STREAM, 0);

	server_address.sin_family = AF_INET;
	server_address.sin_addr.s_addr = htonl(INADDR_ANY );
	server_address.sin_port = htons(port);
	server_len = sizeof(server_address);

	bind(server_socketfd, (struct sockaddr *) &server_address, server_len);

	listen(server_socketfd, 5);

	FD_ZERO(&readfds);
	FD_SET(server_socketfd, &readfds);
	maxfd = server_socketfd;

	printf("traininfo_thread start.\n");

	while (true) {
		int fd;
		int nread;

		tempfds = readfds;

		printf("traininfo_thread server waiting\n");
		result = select(maxfd + 1, &tempfds, NULL, NULL, NULL );

		if (result < 1) {
			perror("traininfo_transfer.c: error\n");
			break;
		}

		for (fd = 0; fd <= maxfd; fd++) {
			if (FD_ISSET(fd,&tempfds)) {
				if (fd == server_socketfd) {
					client_len = sizeof(client_address);
					client_socketfd = accept(server_socketfd,
							(struct sockaddr*) &client_address,
							(socklen_t*) &client_len);
					FD_SET(client_socketfd, &readfds);
					if (client_socketfd > maxfd) {
						maxfd = client_socketfd;
					}
					printf("traininfo_thread add client on fd %d\n",
							client_socketfd);
				} else {
					ioctl(fd, FIONREAD, &nread);
					if (nread == 0) {
						close(fd);
						FD_CLR(fd, &readfds);
						printf("traininfo_thread remove client in fd %d\n", fd);
					} else {
						struct traininfo_request_type type;
						read(fd, &type, sizeof(type));
						switch (type.type) {
						case TYPE_QUERY_SQLETIME: {
							struct stationinfo station;
							read(fd, &station, sizeof(station));
							bool query_result = true;
							query_result = query_start_sale_time(&station);
							write(fd, &query_result, sizeof(query_result));
							if (query_result) {
								write(fd, &station, sizeof(station));
							}
							break;
						}
						case TYPE_SEARCH_TRAIN_NUM: {
							struct train_number_request request;
							read(fd, &request, sizeof(request));
							StationList stationlist; //声明链表
							InitializeListStation(&stationlist); //初始化链表
							bool search_result = true;
							search_result = search_train_number(&request,
									&stationlist);
							write(fd, &search_result, sizeof(search_result));
							if (search_result) {
								StationNode *node = stationlist;
								bool islast = false;
								while (node != NULL ) {
									StationItem item = node->item;
									write(fd, &item, sizeof(item));
									node = node->next;
									if (node == NULL ) {
										islast = true;
									}
									write(fd, &islast, sizeof(islast));
								}
							}
							EmptyTheListStation(&stationlist); //释放链表
							break;
						}
						case TYPE_SEARCH_START_END_STATION: {
							struct train_start_end_station_request request;
							read(fd, &request, sizeof(request));
							StartEndStationList start_end_stationlist; //声明链表
							InitializeListStartEndStation(
									&start_end_stationlist); //初始化链表
							bool search_result = true;
							search_result = search_start_end_station(&request,
									&start_end_stationlist);
							write(fd, &search_result, sizeof(search_result));
							if (search_result) {
								StartEndStationNode *node =
										start_end_stationlist;
								bool islast = false;
								while (node != NULL ) {
									StartEndStationItem item = node->item;
									write(fd, &item, sizeof(item));
									node = node->next;
									if (node == NULL ) {
										islast = true;
									}
									write(fd, &islast, sizeof(islast));
								}
							}
							EmptyTheListStartEndStation(&start_end_stationlist); //释放链表
							break;
						}
						case TYPE_SEARCH_STATION_PASS_TRAIN: {
							struct station_pass_train_request request;
							read(fd, &request, sizeof(request));
							StationPassTrainList station_pass_train_list; //声明链表
							InitializeListStationPassTrain(
									&station_pass_train_list); //初始化链表
							bool search_result = true;
							search_result = search_station_pass_train(&request,
									&station_pass_train_list);
							write(fd, &search_result, sizeof(search_result));
							if (search_result) {
								StationPassTrainNode *node =
										station_pass_train_list;
								bool islast = false;
								while (node != NULL ) {
									StationPassTrainItem item = node->item;
									write(fd, &item, sizeof(item));
									node = node->next;
									if (node == NULL ) {
										islast = true;
									}
									write(fd, &islast, sizeof(islast));
								}
							}
							EmptyTheListStationPassTrain(
									&station_pass_train_list); //释放链表
							break;
						}
						case TYPE_SEARCH_TICKET_LEFT: {
							struct ticket_left_request request;
							read(fd, &request, sizeof(request));
							TicketList ticket_list; //声明链表
							InitializeListTicket(&ticket_list); //初始化链表
							bool search_result = true;
							search_result = search_ticket_left(&request,
									&ticket_list);
							write(fd, &search_result, sizeof(search_result));
							if (search_result) {
								TicketNode *node = ticket_list;
								bool islast = false;
								while (node != NULL ) {
									TicketItem item = node->item;
									write(fd, &item, sizeof(item));
									node = node->next;
									if (node == NULL ) {
										islast = true;
									}
									write(fd, &islast, sizeof(islast));
								}
							}
							EmptyTheListTicket(&ticket_list); //释放链表
							break;
						}
						case TYPE_BUY_TICKET: {
							struct buy_ticket_request request;
							read(fd, &request, sizeof(request));
							struct ticket_saled_info ticket;
							memset(&ticket, 0, sizeof(ticket));
							bool buy_result = true;
							buy_result = buy_ticket(&request, &ticket);
							write(fd, &buy_result, sizeof(buy_result));
							if (buy_result) {
								write(fd, &ticket, sizeof(ticket));
							}
							break;
						}
						default: {
							perror("traininfo_thread request type error\n");
							break;
						}
						}
					}
				}
			}
		}
	}

	pthread_exit("traininfo_thread exit failure!");
}
